/**
 * 【基本说明】：
 * 本文件为MobileIMSDK-Web版浏览器端demo的主js文件。
 *
 * 【重要提示】：
 * 本文件不属于MobileIMSDK-Web版核心，仅用于方便随时随地测试验证
 * MobileIMSDK-Web而已，开发者引用sdk时无需带入本文件。
 */

$(function() {

  //************************************************************ 【1】Demo的全局变量定义 START
  // FIXME [配置项] 部署到正式服务器时，以下可能需要重新指定哦
  // const IM_SERVER_URL = "http://192.168.0.56:3000"; // Web IM服务器地址
  const IM_SERVER_URL = "http://192.168.1.108:3000";

  //** Initialize ui variables
  var d = document, w = window;
  var $window = $(window);
  var $usernameInput = $('#username');   // Input for username
  var $loginButton = $('#loginButton');
  var $messages = $('#message');         // Messages area
  var $inputMessage = $('#content');     // Input message input box
  var $sendMessageButton = $('#sendMessageButton');
  var $receiverInput = $('#receiver');   // 消息接收者输入框
  var $loginHint = $('.login_hint');     // 登陆框下方的信息提示区
  //************************************************************ 【1】Demo的全局变量定义 END


  //************************************************************ 【2】设置MobileIMSDK-Web的回调函数 START
  //** 【WEBIM的SDK调用第1步：设置回调函数】// TODO [1]

  // 开启或关闭MobileIMSDK-Web的框架内部Log输出，建议仅在调试时设为true
  IMSDK.setDebugEnable(false);

  /**
   * 【设置MobileIMSDK-Web的回调方法1：用于debug的log输出】。
   *
   * 框架回调时传入的参数1（必填）：字符串类型，表示log内容；
   * 框架回调时传入的参数2（可选）：bool量，true表示输出到console，否则默认方式(由开发者设置的回调决定)；
   * 建议本回调的用途：开发者可在此回调中按照自已的意图打印MobileIMSDK-Web框架中的log，方便调试时使用。
   */
  IMSDK.callback_log = log;

  /**
   * 【设置MobileIMSDK-Web的回调方法2：用于收到聊天消息时在UI上展现出来（事件通知于收到IM消息时）】。
   *
   * 框架回调时传入的参数1（必填）：Protocal对象(Protocal详情请见
   *          “/libs/mobileimsdk-client-common.js”下的createCommonData4函数说明)；
   * 建议本回调的用途：开发者可在此回调中处理收到的各种IM消息。
   */
  IMSDK.callback_showChatMessage = showChatMessage;

  /**
   * 【设置MobileIMSDK-Web的回调方法3：服务端对客户端提交的登陆请求处理完成后的回调（事件通知于成功登陆/认证后）】。
   *
   * 框架回调时传入的参数：无参数；
   * 建议本回调的用途：开发者可在此回调中进行登陆IM服务器成功后的处理。
   */
  IMSDK.callback_afterLoginSucess = afterLoginSucess;

  /**
   * 【设置MobileIMSDK-Web的回调方法4：客户端的登陆请求被服务端认证失败后的回调（事件通知于 登陆/认证 失败后）】。
   * 补充说明：登陆/认证失败的原因可能是用户名、密码等不正确等，但具体逻辑由服务端的 callBack_checkAuthToken
   *          回调函数去处理。
   *
   * 调用时传入的参数：true表示是掉线重连后的认证失败（在登陆其间可能用户的密码信息等发生了变更），否则表示首次登陆时的认证失败；
   * 建议本回调的用途：开发者可在此回调中提示用户登陆IM服务器失败。
   */
  IMSDK.callback_afterLoginFailed = afterLoginSucessFailed;

  /**
   * 【设置MobileIMSDK-Web的回调方法5：网络连接已断开时的回调（事件通知于与服务器的网络断开后）】。
   *
   * 框架时传入的参数：无参数；
   * 建议本回调的用途：开发者可在此回调中处理掉线时的界面状态更新等，比如设置将界面上的“在线”文字更新成“离线”。
   */
  IMSDK.callback_disconnected = afterDisconnected;

  /**
   * 【设置MobileIMSDK-Web的回调方法6：掉线重连成功后的回调（事件通知于掉线重连成功后）】。
   *
   * 框架时传入的参数：无参数；
   * 建议本回调的用途：开发者可在此回调中处理掉线重连成功后的界面状态更新等，比如设置将界面上的“离线”文字更新成“在线”。
   */
  IMSDK.callback_reconnectSucess = afterReconnectSucess;
  //************************************************************ 【2】设置MobileIMSDK-Web的回调函数 END


  //************************************************************ 【3】Demo的界面点击事件处理 START
  //** 添加键盘事件
  $window.keydown(function (event) {
    // Auto-focus the current input when a key is typed
    if (!(event.ctrlKey || event.metaKey || event.altKey)) {
      if(!IMSDK.isLogined()){
        $inputMessage.focus();
      }
    }
    // When the client hits ENTER on their keyboard
    if (event.which === 13) {
      fireSubmit();
    }
  });

  //** 添加鼠标点击事件
  $loginButton.click(function () {
    fireSubmit();
  });
  $sendMessageButton.click(function () {
    fireSubmit();
  });
  //************************************************************ 【3】Demo的界面点击事件处理 END


  //************************************************************ 【4】Demo的具体功能实现代码 START
  /**
   * 点击登陆界面上“提交”按钮或登陆成功后聊天界面上“发送”按钮时要调用的方法。
   */
  function fireSubmit() {
    // 登陆/认证后的才能发消息
    if (IMSDK.isLogined()) {
      doSend();
    }
    // 没登陆的先登陆再说
    else {
      doLogin();
    }
  }

  /**
   * 执行登陆/连接MobileIMSDK-Web版服务端。
   */
  function doLogin () {
    // 登陆认证时需要的用户名（请确保全局唯一）
    var _username = $usernameInput.val().trim();

    // 要提交给服务端的完整登陆认证信息JSON对象，请确保至少需要loginUserId字段（且字段名不能随意更改）
    var loginInfo = {loginUserId:_username, loginToken:'47384h3uhjfh3j4j343j434h43'};

    // 先尝试清空前次登陆的提示信息
    log('');

    if (_username) {
      log("登陆中....");

      // 【WEBIM的SDK调用第2步：提交登陆/认证信息】// TODO [2]
      IMSDK.loginImpl(loginInfo, IM_SERVER_URL, false);
    }
    else{
      log('请输入登陆用户名！');
    }
  }

  /**
   * 点击“发送”按钮时执行的方法（即发出一条聊天消息）。
   */
  function doSend () {
    var receiver = $receiverInput.val().trim();
    var message = $inputMessage.val().trim();

    // if there is a non-empty message and a socket connection
    if (receiver && message && IMSDK.isOnline()) {
      // 清空输入框
      $inputMessage.val('');

      // tell server to execute 'new message' and send along one parameter
      var p = createCommonData(message, IMSDK.getLoginInfo().loginUserId, receiver);
      // 将本地发出的消息显示在消息列表
      showChatMessage(p);

      // 将消息通过websocket发送出去
      IMSDK.sendData(p);
    }
    else{
      if(!receiver) {
        window.alert('消息接收者是空的！');
      }
      else if(!message) {
        window.alert('要发送的内容是空的！');
      }
      else if(!IMSDK.isOnline()){
        window.alert('online==false, 当前已离线，无法发送消息！');
      }
    }
  }

  /**
   * 添加一条聊天信息到消息列表.
   *
   * 【补充说明】：在当前的演示代码中，本函数将被MobileIMSDK-Web框架回调，请见IMSDK.callback_showChatMessage 回调函数的设置。
   * 【建议用途】：开发者可在此回调中处理收到的各种IM消息。
   *
   * @param p 完整MobileIMSDK的协议包Protocal对象，MobileIMSDK-Web框架回调时传入（关
   *          于Protocal的定义，详见/libs/mobileimsdk-client-common.js下的createCommonData4函数说明）
   * @param options 保留字段暂未用到，MobileIMSDK-Web框架回调时传入
   */
  function showChatMessage (p, options) {
    var isme = (p.from == IMSDK.getLoginInfo().loginUserId) ? true : false;
    var contentDiv = '<div>'+ p.dataContent+'</div>';
    var usernameDiv = '<span>'+ p.from+'</span>';

    var section = d.createElement('section');
    if(isme){
      section.className = 'user';
      section.innerHTML = contentDiv + usernameDiv;
    }
    else {
      section.className = 'service';
      section.innerHTML = usernameDiv + contentDiv;
    }

    // 不应使用appendChild，因$mesage是jQuery对象，它的append方法就相当于DOM的appendChild
    $messages.append(section);
    scrollToBottom();
  }

  /**
   * 登陆/认证成功后要做的事（即首次登陆成功时）。
   *
   * 【补充说明】：在当前的演示代码中，本函数将被MobileIMSDK-Web框架回调，请见IMSDK.callback_afterLoginSucess 回调函数的设置。
   * 【建议用途】：开发者可在此回调中进行登陆IM服务器成功后的处理。
   */
  function afterLoginSucess(){
    ////
    //if (!IMSDK.isLogined()) {
      // 将登出框隐藏并显示登陆成功后的聊天界面
      d.getElementById("showusername").innerHTML = w.IMSDK._loginInfo.loginUserId;
      d.getElementById("loginbox").style.display = 'none';
      d.getElementById("chatbox").style.display = 'block';
    //}
    //// 掉线重连成功时
    //else{
    //  // do nothing
    //}
  }

  /**
   * 客户端的登陆请求被服务端认证失败后的回调（事件通知于 登陆/认证 失败后）.
   *
   * 【补充说明】：在当前的演示代码中，本函数将被MobileIMSDK-Web框架回调，请见IMSDK.callback_LoginSucessFailed 回调函数的设置。
   * 【建议用途】：开发者可在此回调中提示用户登陆IM服务器失败。
   *
   * @param isReconnect true表示是掉线重连后的认证失败（在登陆其间可能用户的密码信息等发生了变更），否则表示首次登陆时的认证失败；
   */
  function afterLoginSucessFailed(isReconnect){
    log('[Demo] 对不起，你'+(isReconnect?'自动重连':'登陆')+'IM服务器失败了 ...', false);
  }

  /**
   * 与IM服务端的网络连接断开时要调用的函数。
   *
   * 【补充说明】：在当前的演示代码中，本函数将被MobileIMSDK-Web框架回调，请见IMSDK.callback_disconnected 回调函数的设置。
   * 【建议用途】：开发者可在此回调中处理掉线时的界面状态更新等，比如设置将界面上的“在线”文字更新成“离线”。
   */
  function afterDisconnected(){
    log('[Demo] Sorry，你掉线了 ...', false);
  }

  /**
   * 掉线重连成功时要调用的函数。
   *
   * 【补充说明】：在当前的演示代码中，本函数将被MobileIMSDK-Web框架回调，请见IMSDK.callback_reconnectSucess 回调函数的设置。
   * 【建议用途】：开发者可在此回调中处理掉线重连成功后的界面状态更新等，比如设置将界面上的“离线”文字更新成“在线”。
   */
  function afterReconnectSucess(){
    log('[Demo] 掉线自动重连成功了！', false);
  }

  /**
   * 让浏览器滚动条保持在最低部。
   */
  function scrollToBottom(){
    w.scrollTo(0, $messages.height());
  }

  /**
   * 添加一条登陆debug信息用于提示用户，方便调试。
   *
   * @param content
   */
  function showLoginHint(content){
    if(content && content.length > 0){
      var $hintSpan = $('<span style="display:block;color:#080;font-size: 12px;"/>')
          .text('☢ ['+formatDate(new Date(), 'MM/dd hh:mm:ss.S') + '] ' +content);
      $loginHint.append($hintSpan);
    }
    // 空字符串表示清空之前的提示内容
    else{
      // 清空div下的内容
      $loginHint.empty();
    }
  }

  /**
   * 用于显示log信息，方便调试。
   *
   * 【补充说明】：在当前的演示代码中，本函数将被MobileIMSDK-Web框架回调，请见IMSDK.callback_log 回调函数的设置。
   * 【建议用途】: 开发者可在此回调中按照自已的意图打印MobileIMSDK-Web框架中的log，方便调试时使用。
   *
   * @param message 要显示的Log内容
   * @param toConsole true表示显示到浏览器的控制台，否则直接显示到网页前端
   */
  function log (message, toConsole) {

    var logMsg = '☢ ['+formatDate(new Date(), 'MM/dd hh:mm:ss.S') + '] ' + message;
    if(toConsole){
      console.debug(logMsg);
    }
    else {
      // 已登陆则将信息显示在聊天界面
      if(IMSDK.isLogined()) {
        //添加系统消息
        var html = '';
        html += '<div class="msg-system">';
        html += logMsg;
        html += '</div>';
        var section = d.createElement('section');
        section.className = 'system J-mjrlinkWrap J-cutMsg';
        section.innerHTML = html;
        $messages.append(section);
        scrollToBottom();
      }
      // 未登陆时则将信息显示在登陆框下方的提示区
      else {
        showLoginHint(message);
      }
    }
  }
  //************************************************************ 【4】Demo的具体功能实现代码 END
});

